/*
 * cudanBaseMemory.cpp
 *
 *  Created on: Dec 8, 2009
 *      Author: daniel
 */

namespace CUDAN
{
	// Default constructor.
	template<typename T, int D>
	BaseMemory<T,D>::BaseMemory() : memory(NULL), sizeDim(DimensionSizeVector(D)), size(0)
	{
#ifdef _DEBUG
		std::cout << "BaseMemory<T,D>::BaseMemory()" << std::endl;
#endif
	}

	// Returns the total number of elements in memory by calculating dimension size.
	template<typename T, int D>
	int BaseMemory<T,D>::getSize(DimensionSizeVector& dim)
	{
#ifdef _DEBUG
		std::cout << "int BaseMemory<T,D>::getSize(DimensionSizeVector& dim)" << std::endl;
#endif
		unsigned int size = 1;

		// Multiply the dimension sizes by each other.
		DimensionSizeVector::iterator i;
		for(i = dim.begin(); i != dim.end(); i++) size *= *i;

		return size;
	}

	// Returns a linear index using an N dimensional index, nindex, with the members dimension size.
	template<typename T, int D>
	int BaseMemory<T,D>::getIndex(DimensionSizeVector& nindex)
	{
#ifdef _DEBUG
		std::cout << "int BaseMemory<T,D>::getIndex(DimensionSizeVector& dim)" << std::endl;
#endif
		// Ensure the number of dimensions in dim are the same as the
		// member's number of dimension.
		if(this->sizeDim.size() != nindex.size()) return 0;

		// Boundary check dim's indexes.
		for(int i = 0; i < D; i++) {
			if(nindex[i] < 0 || nindex[i] > this->sizeDim[i])	return 0;
		}

		// Calculate the linear index.
		int l = nindex[D-1];

		for (int i = (D-2); i >= 0; --i  )
		{
			l *= this->sizeDim[(i)];
			l += nindex[i];
		}

		return l;
	}

	// Returns a linear index using an N dimensional index, index, with the members dimension size.
	template<typename T, int D>
	int BaseMemory<T,D>::getIndex(int index[D])
	{
#ifdef _DEBUG
		std::cout << "int BaseMemory<T,D>::getIndex(int index[D])" << std::endl;
#endif
		// Warning. No boundary checking.

		// Calculate the linear index.
		int l = index[D-1];

		for (int i = (D-2); i >= 0; --i  )
		{
			l *= this->sizeDim[(i)];
			l += index[i];
		}

		return l;
	}
}
